﻿using System;
using System.Text;
using System.Collections.Generic;

namespace TDD.SpreadSheet
{
    internal class Cell
    {
        internal class SpecialValues
        {
            public const string ERROR = "#Error";
            public const string CIRCULAR = "#Circular";
            public const string DECIMAL_DEFAULT_VALUE = "0";
        }

        public Cell(string name)
            : this()
        {
            Name = name;
        }

        private Cell()
        {
            Literal = string.Empty;
            Value = string.Empty;
            RelatedCells = new List<Cell>();
        }

        public string Name
        { get; set; }

        public List<Cell> RelatedCells
        { get; set; }

        public string Literal { get; set; }

        public string Value { get; set; }

        #region "Static constructor"
        static Cell()
        {
            ASCIIA = Encoding.ASCII.GetBytes("A")[0];
            ASCIIZ = Encoding.ASCII.GetBytes("Z")[0];
        }
        #endregion

        #region "Static Properties"
        private static int ASCIIA
        {
            get;
            set;
        }
        private static int ASCIIZ
        {
            get;
            set;
        }
        #endregion

        #region "Static methods"
        internal static bool IsValidColumn(string column)
        {
            char[] letters = column.ToCharArray();
            for (int i = 0; i < letters.Length; i++)
            {
                if (!char.IsLetter(letters[i]))
                {
                    return false;
                }
            }

            return true;
        }
        internal static int GetColumNumber(string column)
        {
            int countLetters = ASCIIZ - ASCIIA + 1;
            char[] letters = column.ToCharArray();
            int sum = 0;

            for (int i = column.Length - 1; i >= 0; i--)
            {
                sum += (letters[column.Length - 1 - i] - ASCIIA + 1) * Convert.ToInt32(Math.Pow(countLetters, i));
            }

            return sum;
        }
        internal static void SplitColumnAndRow(string cell, out int column, out int row)
        {
            char[] letters = cell.ToCharArray();
            string columnName = string.Empty;
            string rowNumber = string.Empty;
            for (int i = 0; i < letters.Length; i++)
            {
                if (!char.IsLetter(letters[i]))
                {
                    break;
                }
                columnName += letters[i].ToString();
            }
            if (columnName == string.Empty)
            {
                throw new ArgumentException(string.Format("The cell {0} is not a valid cell format.", cell), "cell");
            }
            column = GetColumNumber(columnName) - 1;
            rowNumber = cell.Substring(columnName.Length);
            if (!int.TryParse(rowNumber, out row))
            {
                throw new ArgumentException(string.Format("The cell {0} is not a valid cell format.", cell), "cell");
            }
            if (row == 0)
            {
                throw new ArgumentException(string.Format("The cell {0} is not a valid cell format.", cell), "cell");
            }
            row--;
        }
        #endregion

        #region "Equility"
        public override int GetHashCode()
        {
            return Name.GetHashCode();
        }
        public override bool Equals(object obj)
        {
            Cell aux = obj as Cell;
            if (aux == null)
            {
                return false;
            }
            return Name == aux.Name;
        }
        #endregion
    }
}
